/**
 * 
 */
package com.google.code.cisx.gwt.client.components.login;

import com.google.code.cisx.gwt.client.event.EventManager;
import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.ChangeListener;
import com.google.gwt.user.client.ui.ClickListener;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.HTMLTable;
import com.google.gwt.user.client.ui.HasAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.KeyboardListenerAdapter;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.PasswordTextBox;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;

/**
 * Wraps up the Login form.
 * 
 * @author <a href='mailto:rahul.thakur.xdev@gmail.com'>Rahul Thakur</a>
 * @version $Id: LoginComponent.java 266 2009-01-21 06:38:36Z rahul.thakur.xdev $
 * @since 1.0
 */
public class LoginComponent extends Composite {

  private static final LoginConstants messages = (LoginConstants) GWT.create(LoginConstants.class);

  private final Label message = new Label();

  private final VerticalPanel vp = new VerticalPanel();

  private final Label errorMessage = new Label();

  private final Grid grid = new Grid(3, 2);

  private final TextBox username = new TextBox();

  private final Label usernameLabel = new Label(messages.usernamePrompt());

  private final PasswordTextBox password = new PasswordTextBox();

  private final Label passwordLabel = new Label(messages.passwordPrompt());

  private final Image wait = new Image(GWT.getModuleBaseURL() + "img/wait-24x24.gif");

  private final SimplePanel waitPanel = new SimplePanel();

  private final HorizontalPanel loginPanel = new HorizontalPanel();

  private final Button login = new Button(messages.loginButton());

  /**
   * 
   */
  public LoginComponent() {
    super();
    initWidget(vp);

    // build the login component here
    vp.setHorizontalAlignment(VerticalPanel.ALIGN_CENTER);
    vp.add(message);
    vp.add(errorMessage);
    vp.add(grid);

    grid.setWidget(0, 0, usernameLabel);
    grid.setWidget(0, 1, username);

    grid.setWidget(1, 0, passwordLabel);
    grid.setWidget(1, 1, password);

    loginPanel.setWidth("100%");
    loginPanel.setHorizontalAlignment(HorizontalPanel.ALIGN_RIGHT);
    final HorizontalPanel grouper = new HorizontalPanel();
    grouper.add(waitPanel);
    grouper.add(login);
    loginPanel.add(grouper);
    login.setEnabled(false);
    grid.setWidget(2, 1, loginPanel);

    final HTMLTable.CellFormatter cellFormatter = grid.getCellFormatter();
    cellFormatter.setWidth(2, 1, "1px");
    cellFormatter.setHorizontalAlignment(2, 1, HasAlignment.ALIGN_RIGHT);

    usernameLabel.addClickListener(new ClickListener() {
      public void onClick(final Widget sender) {
        username.setFocus(true);
      }
    });

    passwordLabel.addClickListener(new ClickListener() {
      public void onClick(final Widget sender) {
        password.setFocus(true);
      }
    });

    final LoginKeyboardListener keyboardListener = new LoginKeyboardListener();
    username.addKeyboardListener(keyboardListener);
    password.addKeyboardListener(keyboardListener);

    final LoginChangeListener loginChangeListener = new LoginChangeListener();
    username.addChangeListener(loginChangeListener);
    password.addChangeListener(loginChangeListener);

    login.addClickListener(new ClickListener() {
      public void onClick(final Widget sender) {
        login();
      }
    });

  }

  /**
   * Trigger a login event. This is the equivalent of the user clicking the Login button.
   */
  public void login() {
    login.setEnabled(false);
    // waitPanel.add(wait); // TODO: Enable wait image!
    // loginListener.onSubmit(this);

    if (true) {
      // clear any message on the Login Panel
      message.setText(""); // clear before any new msgs are added.
      errorMessage.setText(""); // clear before any new msgs are added.

      LoginService.Util.getAsyncInstance().login(username.getText(), password.getText(), new AsyncCallback() {

        public void onFailure(Throwable caught) {
          errorMessage.setText("System error! Please try again later.");
        }

        public void onSuccess(Object result) {
          if (result instanceof String) {
            if (((String) result).equals(LoginService.SC_SUCCESS)) {
              message.setText("Login Successful!");
              EventManager.getInstance().dispatchEvent(new LoginEvent(this, LoginEvent.LoginEventType.LOGIN));
            } else {
              errorMessage.setText("Login Failed!");
              EventManager.getInstance().dispatchEvent(new LoginEvent(this, LoginEvent.LoginEventType.LOGOUT));
            }
          }
          // else do nothing
        }
      });
    } else {
      // TODO: Remove this ELSE block after testing
      // Lets just simulate the case of errors
      message.setText(""); // clear before any new msgs are added.
      errorMessage.setText(""); // clear before any new msgs are added.
      if (username.getText().equals("admin") && password.getText().equals("admin123")) {
        message.setText("Login Successful!");
        EventManager.getInstance().dispatchEvent(new LoginEvent(this, LoginEvent.LoginEventType.LOGIN));
      } else {
        errorMessage.setText("Login failed!");
        EventManager.getInstance().dispatchEvent(new LoginEvent(this, LoginEvent.LoginEventType.LOGOUT));
      }
    }
  }

  /**
   * Listen for key presses and update the login button.
   */
  private class LoginKeyboardListener extends KeyboardListenerAdapter {
    public void onKeyUp(final Widget sender, final char keyCode, final int modifiers) {
      // updateLoginEnabled();
      if (keyCode == KEY_ENTER) {
        if (login.isEnabled()) {
          login.click();
        }
      } else {
        if (username.getText().length() >= 5 && password.getText().length() >= 5)
          login.setEnabled(true);
        else
          login.setEnabled(false);
      }
    }

  }

  /**
   * Listen for changes and update the login button.
   */
  private class LoginChangeListener implements ChangeListener {
    public void onChange(final Widget sender) {
      // updateLoginEnabled();
      // TODO: What do we need to do here?
    }
  }
}
